package com.scy.rsa;

import org.apache.commons.codec.binary.Base64;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;

/**
 * SignatureDemo: 私钥加密,公钥验签
 *
 * @Author: 马伟奇
 * @CreateTime: 2020-05-09
 * @Description:
 */
public class SignatureDemo {
    public static void main(String[] args) throws Exception {

        String plainText = "你好abc123";

        PublicKey publicKey = RSADemo.getPublicKey(RSADemo.publicKeyFileName, RSADemo.algorithm);
        PrivateKey privateKey = RSADemo.getPrivateKey(RSADemo.privateKeyFileName, RSADemo.algorithm);

        //通过查看Signature的类文档.知道算法有以下几种
        //        SHA1withDSA
        //        SHA1withRSA
        //        SHA256withRSA
        String algorithm = "SHA256withRSA";

        // 获取数字签名
        String signatureEncryptCipherText = getSignature(plainText, algorithm, privateKey);
        System.out.println("私钥加密后的数字签名的密文:"+signatureEncryptCipherText);

        // 当更改plainText内容时,看到校验结果就为false了
        plainText = "你好abc12";
        // 校验签名
        boolean result = verifySignature(plainText, algorithm, publicKey, signatureEncryptCipherText);
        System.out.println("签名验证的结果是:" + result);
    }

    /**
     * 用公钥校验数字签名
     *
     * @param plainText                  表示明文
     * @param algorithm                  表示算法
     * @param publicKey                  公钥key
     * @param signatureEncryptCipherText 数字签名的密文
     * @return
     */
    private static boolean verifySignature(String plainText, String algorithm, PublicKey publicKey, String signatureEncryptCipherText) throws Exception {
        // 获取签名对象
        Signature signature = Signature.getInstance(algorithm);
        // 初始化校验
        signature.initVerify(publicKey);
        // 传入原文
        signature.update(plainText.getBytes());
        // 校验数据
        return signature.verify(Base64.decodeBase64(signatureEncryptCipherText));
    }

    /**
     * 用私钥生成数字签名
     *
     * @param plainText  明文
     * @param algorithm  表示算法
     * @param privateKey 私钥key
     * @return 签名后的数据（加密的密文）
     */
    private static String getSignature(String plainText, String algorithm, PrivateKey privateKey) throws Exception {

        // 获取签名对象
        Signature signature = Signature.getInstance(algorithm);
        // 初始化签名
        signature.initSign(privateKey);
        // 传入明文
        signature.update(plainText.getBytes());

        // 开始签名
        byte[] signatureEncryptByteArray = signature.sign();

        return Base64.encodeBase64String(signatureEncryptByteArray);
    }
}